using System.Reflection;
using StudentVideo.Common.Attributes;
using StudentVideo.Common.Constants;

namespace StudentVideo.Common.Exceptions;

/// <summary>
/// HTTP 错误处理
/// </summary>
/// <param name="msg"></param>
/// <param name="statusCode"></param>
public class HttpException(string msg, int statusCode): Exception(ValidateMessage(msg)) {
   private static int DefaultCode => 400;

   public int StatusCode { get; private set; } = statusCode;

   /// <summary>
   /// HTTP 错误处理
   /// </summary>
   /// <param name="msg"></param>
   public HttpException(string msg) : this(msg, GetDefaultStatusCode(msg)) { }

   private static string ValidateMessage(string msg) {
      Type type = typeof(HttpErrorMessage);

      // 检查常量字段
      var fields = type.GetFields(BindingFlags.Public | BindingFlags.Static)
                      .Where(f => f.IsLiteral && !f.IsInitOnly);

      // 检查静态属性
      var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Static);

      bool isValid = fields.Any(f => f.GetValue(null)?.ToString() == msg) ||
                    properties.Any(p => p.GetValue(null)?.ToString() == msg);

      if (!isValid) {
         throw new ArgumentException(
             $"消息 '{msg}' 不是有效的 HttpErrorMessage 成员",
             nameof(msg)
         );
      }

      return msg;
   }

   private static int GetDefaultStatusCode(string msg) {
      Type type = typeof(HttpErrorMessage);

      // 查找匹配的字段
      var field = type
         .GetFields(BindingFlags.Public | BindingFlags.Static)
         .FirstOrDefault(f => f.IsLiteral && !f.IsInitOnly && f.GetValue(null)?.ToString() == msg);

      if (field != null) {
         var statusCodeAttr = field.GetCustomAttribute<HttpErrorCodeAttribute>();
         return statusCodeAttr?.StatusCode ?? DefaultCode;
      }

      // 查找匹配的属性
      var property = type
         .GetProperties(BindingFlags.Public | BindingFlags.Static)
         .FirstOrDefault(p => p.GetValue(null)?.ToString() == msg);

      if (property != null) {
         var statusCodeAttr = property.GetCustomAttribute<HttpErrorCodeAttribute>();
         return statusCodeAttr?.StatusCode ?? DefaultCode;
      }

      return DefaultCode;
   }
}
